package examples.game.msgservice;

import framework.Trait;
import framework.server.ServerException;
import framework.service.MessageService;
import examples.game.BullsAndCows;
import examples.game.Digits;
import examples.game.Match;

/**
 * Example service playing the game Bulls And Cows.
 * 
 * Example services.xml
 * <pre>
 * &lt;services&gt;
 *   &lt;service name="player1"
 *            class="examples.game.msgservice.BullsAndCowsService"
 *            path="../classes"/&gt;
 *   &lt;service name="player2"
 *            class="examples.game.msgservice.BullsAndCowsService"
 *            path="../classes"&gt;
 *     &lt;init&gt;
 *       <param name="opponent" value="player1"/&gt;
 *     &lt;/init&gt;
 *   &lt;/service&gt;
 *   ...
 * &lt;services/&gt;
 * <pre>
 *
 * @author Orlin Tomov
 *
 */
public class BullsAndCowsService extends MessageService {

	private BullsAndCows game;
	public String opponent;
	public Boolean again = true;

	public BullsAndCowsService(Trait container, String serviceName) {
		super(container, serviceName);
		game = new BullsAndCows();
	}

	public String getOpponent() {
		return opponent;
	}

	public void setOpponent(String opponent) {
		this.opponent = opponent;
	}

	public Boolean getAgain() {
		return again;
	}

	public void setAgain(Boolean again) {
		this.again = again;
	}

	/**
	 * Start a game. Sent game invitation if the opponent is known.
	 *
	 * @see framework.Service#init()
	 */
	@Override
	public void init() throws ServerException {
		game.init();
		if (opponent != null) {
			sendMessage(new GameStartMsg(getName()), getName(), opponent);
			/**/log.info("do you wanna play?");
		}
	}

	/**
	 * Starts a game, the opponent is stored and a guess is send back.
	 * @param	message	presents invitation for play; 
	 */
	public void process(GameStartMsg message) {
		if (!again && (opponent == null)) {
			/**/log.info("no");
			return;
		}
		opponent = message.getText();
		Digits nextMove = game.nextMove();
		NextMoveMsg nextMoveMsg = new NextMoveMsg(nextMove);
		sendMessage(nextMoveMsg, getName(), opponent);
		/**/log.info("yes");
		/**/log.info(nextMove);
	}

	/**
	 * Prepares an answer and send back. If the opponent has guess then do
	 * nothing in order opponent send a message for start again. Otherwise if the
	 * Opponent hasn't guess sends next move follows.
	 * 
	 * @param	message	opponent next move
	 */
	public void process(NextMoveMsg message) {
		Digits move = new Digits(message.getDigits());
		Match answer = game.getAnswer(move);
		AnswerMsg answerMsg = new AnswerMsg(answer);
		sendMessage(answerMsg, getName(), opponent);
		/**/log.info(move + " - " + answer);
		if (answer.getBulls() == BullsAndCows.NUM_DIGITS) {
			/**/log.info("lose");
			opponent = null;
			if (again)
			try {
				init();
			} catch (ServerException e) {
				log.error(e.getMessage(), e);
			}
		}
	}

	/**
	 * The result is stored to game. If the opponent has guess then the game
	 * begins from start.
	 * 
	 * @param message
	 *            answer container
	 */
	public void process(AnswerMsg message) {
		Match answer = new Match(message.getBulls(), message.getCows());
		game.setAnswer(answer);
		if (answer.getBulls() == BullsAndCows.NUM_DIGITS) {
			/**/log.info("win");
			if (again)
			try {
				init();
			} catch (ServerException e) {
				log.error(e.getMessage(), e);
			}
		} else {
			Digits nextMove = game.nextMove();
			NextMoveMsg nextMoveMsg = new NextMoveMsg(nextMove);
			sendMessage(nextMoveMsg, getName(), opponent);
			/**/log.info(nextMove);
		}
	}
}
